package info.niwota.web.proxy;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;

import jvs.peer.util.Log;
import x.org.apache.http.ConnectionClosedException;
import x.org.apache.http.HttpException;
import x.org.apache.http.impl.DefaultHttpClientConnection;
import x.org.apache.http.params.HttpParams;
import x.org.apache.http.protocol.BasicHttpContext;
import x.org.apache.http.protocol.HttpService;

public class HttpWorkerThread implements Runnable {
	private static final String TAG = "HttpWorkerThread";

	private final HttpService httpservice;
	private final Socket socket;
	private final HttpParams params;

	public HttpWorkerThread(final HttpService httpservice, HttpParams params,
			Socket socket) {
		super();
		this.httpservice = httpservice;
		this.socket = socket;
		this.params = params;
	}

	public void run() {
		if (Log.DEBUG) {
			Log.d(TAG, "New connection thread " + this);
		}

		final ProxyHttpServerConnection conn = new ProxyHttpServerConnection();
		final ProxyHttpContext context = new ProxyHttpContext(null);
		context.conn = new DefaultHttpClientConnection();
		context.context = new BasicHttpContext(null);

		try {
			conn.bind(socket, this.params);

			while (!Thread.interrupted()) {
				if (!conn.isOpen()) {
					break;
				}

				this.httpservice.handleRequest(conn, context);

				if (conn.isTunneling()) {

					if (Log.DEBUG) {
						Log.d(TAG, "is tunneling: " + conn.isTunneling());
					}

					return;
				}

			}
		} catch (ConnectionClosedException e) {
			if (Log.DEBUG) {
				Log.e(TAG, "Client closed connection", e);
			}
		} catch (SocketTimeoutException e) {
			if (Log.DEBUG) {
				Log.e(TAG, "Client closed connection", e);
			}
		} catch (IOException e) {
			if (Log.DEBUG) {
				Log.e(TAG, "WorkerThread IOException: ", e);
			}
			if (Log.TRACE) {
				e.printStackTrace();
			}
		} catch (HttpException e) {
			if (Log.DEBUG) {
				Log.d(TAG, "Unrecoverable HTTP protocol violation: " + e);
			}
			if (Log.TRACE) {
				e.printStackTrace();
			}
		} finally {
			try {
				if (!conn.isTunneling()) {
					if (Log.DEBUG) {
						Log.d(TAG, "closing connection. tunneling: "
								+ conn.isTunneling());
					}

					conn.shutdown();
				}
			} catch (Exception ignore) {
				//
			}
		}
	}

}
